#!/usr/bin/env python
# -*- coding: utf-8 -*-

import requests
from bs4 import BeautifulSoup
import json
import time
import os
import urllib.parse
from urllib.request import urlretrieve

import sys
import os
# 添加项目根目录到Python路径
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from crawlers.base_crawler import BaseCrawler
from utils.logger_config import get_logger


class ArticleCrawler(BaseCrawler):
    """
    文章爬虫实现类
    继承BaseCrawler，实现具体的爬取逻辑
    返回原始数据而不是ArticleData对象
    """
    
    def __init__(self, config=None):
        super().__init__()
        self.logger = get_logger(__name__)
        self.config = config or {}
        self.session = requests.Session()
        self.session.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
        })
    
    def crawl(self, url: str) -> dict:
        """
        爬取单篇文章信息
        根据提供的HTML结构提取文章标题、内容、图片等
        :param url: 文章URL
        :return: 包含文章数据的字典，失败返回None
        """
        try:
            response = self.session.get(url)
            response.encoding = 'utf-8'
            soup = BeautifulSoup(response.text, 'html.parser')
            
            # 根据提供的HTML结构提取信息
            # 标题在.shadow > .text-center > h5中
            title_element = soup.select_one('.shadow .text-center h5')
            title = title_element.text.strip() if title_element else ''
            
            # 内容在.py-3.content-limit中
            content_element = soup.select_one('.py-3.content-limit')
            content = content_element.decode_contents() if content_element else ''  # 使用decode_contents保留HTML格式
            
            # 创建原始数据字典
            article_data = {
                'title': title,
                'content': content,
                'url': url,
                'images': []  # 存储图片URL
            }
            
            # 提取所有图片URL
            if content_element:
                img_tags = content_element.find_all('img')
                for img in img_tags:
                    src = img.get('src')
                    if src:
                        article_data['images'].append(src)
            
            return article_data
        except Exception as e:
            self.logger.error(f"爬取文章失败: {e}")
            return None
    
    def crawl_article(self, url: str) -> dict:
        """
        爬取单篇文章信息（别名方法，与main.py中的调用保持一致）
        根据提供的HTML结构提取文章标题、内容、图片等
        :param url: 文章URL
        :return: 包含文章数据的字典，失败返回None
        """
        return self.crawl(url)
    
    def get_article_urls(self, base_url: str, max_pages: int = 5, start_page: int = 1, 
                        link_selector: str = '.article-link', page_format: str = None) -> list:
        """
        从分页网站中提取所有文章URL
        :param base_url: 分页网站的基础URL（例如：https://example.com/page/）
        :param max_pages: 最大分页数
        :param start_page: 起始页码（默认为1）
        :param link_selector: 文章链接的CSS选择器
        :param page_format: 分页URL格式，例如：'{base_url}{page}' 或 '{base_url}?page={page}'
        :return: 文章URL列表
        """
        article_urls = []
        for page in range(start_page, start_page + max_pages):
            try:
                # 构建分页URL
                if page_format:
                    url = page_format.format(base_url=base_url, page=page)
                else:
                    # 如果是第一页，则不显示page参数
                    url = f"{base_url}{'' if page == 1 else '/p'+str(page)+'.html'}"
                
                self.logger.info(f"正在获取页面: {url}")
                response = self.session.get(url)
                response.encoding = 'utf-8'
                soup = BeautifulSoup(response.text, 'html.parser')
                
                # 使用指定的选择器查找文章链接
                links = soup.select(link_selector)
                for link in links:
                    href = link.get('href')
                    if href:
                        # 处理相对URL
                        if href.startswith('/'):
                            from urllib.parse import urlparse
                            base_domain = urlparse(base_url).netloc
                            href = f"https://{base_domain}{href}"
                        article_urls.append(href)
                
                self.logger.info(f"已解析第 {page} 页，找到 {len(links)} 条文章链接")
            except Exception as e:
                self.logger.error(f"解析分页失败: {e}")
                break
        
        # 去重
        article_urls = list(set(article_urls))
        self.logger.info(f"总共找到 {len(article_urls)} 个唯一文章URL")
        return article_urls
    
    def download_images(self, article_data: dict, save_dir: str = 'images') -> dict:
        """
        下载文章中的所有图片并保存到本地
        :param article_data: 文章数据字典
        :param save_dir: 图片保存目录
        :return: 图片URL到本地路径的映射字典
        """
        if not article_data or not article_data.get('images'):
            return {}
            
        # 创建保存目录
        if not os.path.exists(save_dir):
            os.makedirs(save_dir)
            
        # 下载每张图片
        image_mapping = {}  # 存储URL到本地路径的映射
        for img_url in article_data['images']:
            try:
                # 解析URL，获取文件名
                parsed_url = urllib.parse.urlparse(img_url)
                filename = os.path.basename(parsed_url.path)
                
                # 如果没有文件名，生成一个
                if not filename:
                    filename = f"image_{int(time.time())}.jpg"
                
                # 完整保存路径
                save_path = os.path.join(save_dir, filename)
                
                # 下载图片
                self.logger.info(f"正在下载图片: {img_url}")
                urlretrieve(img_url, save_path)
                image_mapping[img_url] = save_path
                
            except Exception as e:
                self.logger.error(f"下载图片失败 {img_url}: {e}")
                # 保留原始URL作为备份
                image_mapping[img_url] = img_url
        
        return image_mapping


# 测试单篇文章爬取功能
def test_single_article():
    # 初始化爬虫
    crawler = ArticleCrawler()
    logger = get_logger(__name__)
    
    # 测试URL
    test_url = "https://www.zhuangxingjia.com/zhishi/zxgl/654.html"
    
    # 爬取文章
    article_data = crawler.crawl(test_url)
    
    if article_data:
        logger.info(f"标题: {article_data['title']}")
        logger.info(f"URL: {article_data['url']}")
        logger.info(f"图片数量: {len(article_data['images'])}")
        
        # 下载图片（可选）
        local_images = crawler.download_images(article_data, save_dir='test_images')
        
        # 保存文章内容到文件
        with open(f"article_{int(time.time())}.html", "w", encoding="utf-8") as f:
            f.write(f"<h1>{article_data['title']}</h1>")
            f.write(article_data['content'])
        
        logger.info("文章内容已保存到HTML文件")
    else:
        logger.error("爬取失败")

if __name__ == "__main__":
    test_single_article()